package org.hawk.gwt.ppc.reflect.lang;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.net.URL;

import org.hawk.gwt.ppc.reflect.emul.java.lang.InternalError;

/**
 * Provides access to reflect package. Can be accessed only from
 * {@link ClassDelegate} and used only for hosted mode (for debug purposes).
 * 
 * @author alex.bereznevatiy@gmail.com
 */
public class ReflectAccessor {

	public <T> Constructor<T> createConstructor(Object accessor, ClassDelegate<T> cls, String signature, boolean varArgs) {
		try {
			return cls.toClass().getDeclaredConstructor(
					ClassDelegate.unmarshalSignature(signature));
		} catch (NoSuchMethodException ex) {
			throw new InternalError(ex);
		}
	}

	public Field createField(Object accessor, ClassDelegate<?> cls, String signature) {
		try {
			return cls.toClass().getDeclaredField(signature);
		} catch (NoSuchFieldException ex) {
			throw new InternalError(ex);
		}
	}

	public Method createMethod(Object accessor, ClassDelegate<?> cls, String signature, boolean varArgs) {
		try {
			int i = signature.indexOf('(');
			String name = signature;

			if (i >= 0) {
				name = signature.substring(0, i);
			}
			return cls.toClass().getDeclaredMethod(name,
					ClassDelegate.unmarshalSignature(signature));
		} catch (NoSuchMethodException ex) {
			throw new InternalError(ex);
		}
	}
	
	public Package getPackage(String name) {
		Package pkg = Package.getPackage(name);
		if (pkg != null) {
			return pkg;
		}
		Method m = null;
		try {
			m = ClassLoader.class.getDeclaredMethod("definePackage", String.class, String.class,
				    String.class, String.class, String.class, String.class, String.class, URL.class);
			m.setAccessible(true);
			return (Package) m.invoke(getClass().getClassLoader(), name, null, null, null, null, null, null, null);
		} catch (Throwable th) {
			return null;
		} finally {
			if (m != null) {
				m.setAccessible(false);
			}
		}
	}
}
